package nirvana.core.exceptions;

import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import nirvana.core.domains.vo.ApiResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * GlobalExceptionHand
 *
 * @author linkanyway
 * @version 1.0
 * @date 2024/04/15 21:12
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHand {
    private String splitter = ",";

    private final HttpServletResponse response;

    private Map<Class<? extends Exception>, ExceptionHandlerMethod> exceptionHandlers = new LinkedHashMap<>(  );

    @FunctionalInterface
    public interface ExceptionHandlerMethod {
        ApiResult<?> handleException(Exception e);
    }

    public void registerExceptionHandler(Class<? extends Exception> exceptionClass,
                                         ExceptionHandlerMethod handlerMethod) {
        exceptionHandlers.put (exceptionClass, handlerMethod);
    }

    /**
     * format message
     *
     * @param template
     * @param args
     * @return
     */
    private String formatMessage(String template, String... args) {
        return String.format (template, args);
    }

    @ExceptionHandler(Exception.class)
    public ApiResult<?> handleException(Exception e) {
        log.error (e.getMessage (), e);
        Throwable throwable = e.getCause ();
        ExceptionHandlerMethod handlerMethod = exceptionHandlers.get (e.getClass ());
        if (handlerMethod != null) {
            return handlerMethod.handleException (e);
        } else {
            return ApiResult.error ("操作失败，" + e.getMessage ());
        }
    }


    public GlobalExceptionHand(HttpServletResponse response) {
        this.response = response;
        registerExceptionHandler (BizException.class, e -> {
            log.error (e.getMessage (), e);
            return ApiResult.error (e.getMessage ());
        });

        registerExceptionHandler (NullPointerException.class, e -> {
            log.error (e.getMessage (), e);
            return ApiResult.error ("对象为空，具体信息: " + e.getMessage ());
        });

        registerExceptionHandler (Exception.class, e -> {
            log.error (e.getMessage (), e);
            return ApiResult.error ("异常: " + e.getMessage ());
        });
        // 其他异常处理方法的注册



        //参数校验异常
        registerExceptionHandler(MethodArgumentNotValidException.class,e->{
            MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
            log.error (formatMessage ("参数验证错误，原因是： %s", e.getMessage ()), e);
            List<ObjectError> allErrors = exception.getBindingResult().getAllErrors();
            String message = allErrors.stream()
                    .map(ObjectError::getDefaultMessage)
                    .distinct()
                    .collect(Collectors.joining(","));
            ApiResult result = ApiResult.error(message, allErrors.toArray());
            return result;
        });


    }
}
